package org.example.backend.config.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.example.backend.bean.ControllerLog;
import org.example.backend.mapper.ControllerLogMapper;
import org.example.backend.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Date;

/**
 * @author 啊昌
 * @date 2025/7/19 22:28
 * ControllerLogAspect 收集controller的日志
 */
@Aspect
@Component
@Slf4j
public class ControllerLogAspect {
	@Autowired
	private ControllerLogMapper logMapper; //日志收集

	@Autowired
	private JwtUtils jwtUtils; //日志收集

	/**
	 * 在方法执行前后进行日志记录。
	 *
	 * @param pjp 切面中的连接点
	 * @return 目标方法的返回值
	 * @throws Throwable 目标方法执行过程中可能抛出的异常
	 */
	@Around("execution(* org.example.backend.controller..*.*(..))")
	public Object logController(ProceedingJoinPoint pjp) throws Throwable {
		ControllerLog controllerLog = new ControllerLog();
		Long userIdFromToken = null;
		// 获取HTTP请求
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
				.currentRequestAttributes()).getRequest();
		String token = request.getHeader("Authorization");
		if(!StringUtils.isEmpty(token)) {
			userIdFromToken = jwtUtils.getUserIdFromToken(token);
		}
		controllerLog.setHttpMethod(request.getMethod());
		controllerLog.setRequestUri(request.getRequestURI());
		controllerLog.setClientIp(getClientIp(request));
		controllerLog.setClassMethod(getClassMethod(pjp));
		controllerLog.setClassMethod(getClassMethod(pjp));
		controllerLog.setCreateTime(new Date());
		controllerLog.setUserId(userIdFromToken == null ? 0 : userIdFromToken);
		logMapper.insert(controllerLog);
		Object result = null;
		result = pjp.proceed();//执行目标方法
		return result;
	}

	private String getClassMethod(ProceedingJoinPoint joinPoint) {
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		return signature.getDeclaringTypeName() + "." + signature.getName();
	}

	private String getClientIp(HttpServletRequest request) {
		String ip = request.getHeader("X-Forwarded-For");
		if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		return ip;
	}

}
